using BarManager.Core.ApplicationService.Interfaces;
using BarManager.Core.Entity;
using BarManager.UI.Web.Caching;
using BarManager.UI.Web.HtmlHelpers;
using BarManager.UI.Web.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace BarManager.UI.Web.Controllers
{
    [Authorize(Users = "admin")]
    public class EnvioController : BaseController<EnvioViewModel, Envio, long>
    {
        private IClienteService ClienteService { get; set; }
        private IPromocionService PromocionService { get; set; }
        private ICategoriaService CategoriaService { get; set; }
        private IProductoService ProductoService { get; set; }
        private IEnvioService EnvioService { get { return (IEnvioService)Service; } }

        public EnvioController(IEnvioService service, IPromocionService promocionService, ICategoriaService categoriaService,
             IProductoService productoService, IClienteService clienteService)
            : base(service)
        {
            this.PromocionService = promocionService;
            this.CategoriaService = categoriaService;
            this.ProductoService = productoService;
            this.ClienteService = clienteService;
        }

        public override ActionResult Index(long id = 0)
        {
            EnvioViewModel model = new EnvioViewModel
            {
                Promociones = PromocionService.GetAllActivas().OrderBy(x => x.Descripcion),
                Categorias = CategoriaService.GetAllCategoriasContainsProductos().OrderBy(x => x.Nombre)
            };

            if (id > 0)
            {
                model.Entity = EnvioService.Get(x => x.Id == id);
                model.NombreApellido = model.Entity.Cliente.NombreApellido;
                CacheManager.Set("EnvioViewModel", model);
                CacheManager.Set("EnvioDetalleBase", model.Entity.Detalle.ToList<EnvioDetalleBase>());
            }

            return View(model);
        }

        public ActionResult Index(int clienteId)
        {
            EnvioViewModel model = new EnvioViewModel
            {
                Promociones = PromocionService.GetAllActivas().OrderBy(x => x.Descripcion),
                Categorias = CategoriaService.GetAllCategoriasContainsProductos().OrderBy(x => x.Nombre)
            };

            if (clienteId > 0)
            {
                model.Entity.Cliente = ClienteService.Get(x => x.Id == clienteId);
                model.NombreApellido = model.Entity.Cliente.NombreApellido;                
            }
            return View(model);
        }       

        [HttpGet]
        public ActionResult Cancel(long id = 0)
        {
            if (id > 0) EnvioService.Cancel(id);
            return RedirectToAction("List");
        }

        [HttpGet]
        public ActionResult Invoice(long id = 0)
        {
            if (id > 0) EnvioService.Invoice(id);
            return RedirectToAction("List");
        }

        public override ActionResult List(string filter, int page = 1)
        {
            CacheManager.Clear();
            List<Envio> entities = new List<Envio>();
            long id = 0;

            if (long.TryParse(filter, out id))
                entities = EnvioService.Find(x => x.Id == id).ToList();
            else
                entities = EnvioService.Find(x => (filter == null || x.Cliente.Nombre.Contains(filter) || x.Cliente.Apellido.Contains(filter))
                                                  && (x.Estado == EstadoEnvio.Pendiente || x.Estado == EstadoEnvio.Enviado))
                                             .OrderByDescending(x => x.Total)
                                             .Skip((page - 1) * PageSize)
                                             .Take(PageSize).ToList();

            EnvioViewModel model = new EnvioViewModel
            {
                Entities = entities,
                PagingInfo = new PagingInfo
                {
                    CurrentPage = page,
                    ItemsPerPage = PageSize,
                    TotalItems = EnvioService.Find(x => (filter == null || x.Cliente.Nombre.Contains(filter) || x.Cliente.Apellido.Contains(filter))
                                                  && (x.Estado == EstadoEnvio.Pendiente || x.Estado == EstadoEnvio.Enviado))
                                              .Count()
                }
            };
            model.Filter = filter;     
            return View(model);
        }

        public override ActionResult Save(EnvioViewModel model)
        {
            List<EnvioDetalleBase> detalle = CacheManager.Get<List<EnvioDetalleBase>>("EnvioDetalleBase");
            model.Entity.Detalle = detalle;

            //- Carga combo de categorias
            if (model.Categorias == null) model.Categorias = CategoriaService.GetAllCategoriasContainsProductos().OrderBy(x => x.Nombre);

            //- Carga combo promociones
            if (model.Promociones == null) model.Promociones = PromocionService.GetAllActivas().OrderBy(x => x.Descripcion);

            //- Guarda o actualiza
            if (model.Entity.Id == 0)
                ErrorList = EnvioService.Add(model.Entity);
            else
                ErrorList = EnvioService.Update(model.Entity);

            return ShowError(model, ErrorList, model.Entity.Id);
        }

        [ActionName("FillProductoJson")]
        public JsonResult FillProducto(int id = 0)
        {
            var productos = ProductoService.GetAllProductosByCategoria(id)
                                    .Select(x => new { Id = x.Id, Nombre = x.Nombre })
                                    .OrderBy(x => x.Nombre);
            return this.Json(productos, JsonRequestBehavior.AllowGet);
        }

        [ActionName("FillDomicilioJson")]
        public JsonResult FillDomicilio(int id = 0)
        {
            var domicilios = ClienteService.GetAllDomiciliosByClienteId(id)                                   
                                    .Select(y => new { Id = y.Id, Nombre = y.ToString() })
                                    .OrderBy(x => x.Nombre);
            return this.Json(domicilios, JsonRequestBehavior.AllowGet);
        }

        [HttpPost]
        [ActionName("FindCustomer")]
        public JsonResult BuscarCliente(string search)
        {
            long telefono = 0;
            IEnumerable<Cliente> clientes = null;
            if (long.TryParse(search, out telefono))
                clientes = ClienteService.GetAll().ToList().Where(x => x.Telefono1.ToString().Contains(telefono.ToString())
                                                                    || x.Telefono2.ToString().Contains(telefono.ToString()));
            else
                clientes = ClienteService.GetAll().ToList()
                    .Where(x => x.Nombre.ToLower().Contains(search.ToLower()) 
                             || x.Apellido.ToLower().Contains(search.ToLower()));

            return Json(clientes.Select(x => new { Id = x.Id, NombreApellido = x.NombreApellido, Tel1 = x.Telefono1.ToString(), Tel2 = x.Telefono2.ToString() }), JsonRequestBehavior.AllowGet);
        }

        [HttpPost]
        public PartialViewResult DetalleAdd(EnvioViewModel model)
        {
            bool actualizoCantidad = false;
            //- Cachamos items agregados
            if (!CacheManager.IsSet("EnvioDetalleBase"))
            { CacheManager.Set("EnvioDetalleBase", new List<EnvioDetalleBase>()); }

            //- Creamos nuevo item si es producto
            EnvioDetalleBase item;
            if (model.TipoItem == 1)
            {
                item = new EnvioDetalleProducto
                {
                    Cantidad = model.CantidadProducto,
                    FechaPedido = DateTime.Now,
                    ProductoId = model.Producto.Id,
                    Producto = ProductoService.Get(x => x.Id == model.Producto.Id)
                };

                //- Si existe producto actualizamos solo cantidad
                foreach (var detalle in CacheManager.Get<List<EnvioDetalleBase>>("EnvioDetalleBase"))
                {
                    if (detalle is EnvioDetalleProducto)
                        if (((EnvioDetalleProducto)detalle).ProductoId == model.Producto.Id)
                        {
                            ((EnvioDetalleProducto)detalle).Cantidad += model.CantidadProducto;
                            actualizoCantidad = true;
                        }
                }
                //- Agregamos producto al detalle si es no existe
                if (!actualizoCantidad) CacheManager.Get<List<EnvioDetalleBase>>("EnvioDetalleBase").Add(item);
            }

            //- Creamos nuevo item si es promocion
            if (model.TipoItem == 2)
            {
                item = new EnvioDetallePromocion
                {
                    Cantidad = model.CantidadPromocion,
                    FechaPedido = DateTime.Now,
                    PromocionId = model.Promocion.Id,
                    Promocion = PromocionService.Get(x => x.Id == model.Promocion.Id)
                };

                //- Si existe promocion actualizamos solo cantidad
                foreach (var detalle in CacheManager.Get<List<EnvioDetalleBase>>("EnvioDetalleBase"))
                {
                    if (detalle is EnvioDetallePromocion)
                        if (((EnvioDetallePromocion)detalle).PromocionId == model.Promocion.Id)
                        {
                            ((EnvioDetallePromocion)detalle).Cantidad += model.CantidadPromocion;
                            actualizoCantidad = true;
                        }
                }
                //- Agregamos promocion nueva al detalle si no existe
                if (!actualizoCantidad) CacheManager.Get<List<EnvioDetalleBase>>("EnvioDetalleBase").Add(item);
            }

            //- Actualizamos el detalle en cabecera y metemos en sesion al model
            model.Entity.Detalle = CacheManager.Get<List<EnvioDetalleBase>>("EnvioDetalleBase");
            CacheManager.Set("EnvioViewModel", model);

            //- Devolvemos el model solo al detalle para refrezcar grilla
            return PartialView("_EnvioDetalle", CacheManager.Get<EnvioViewModel>("EnvioViewModel"));
        }

        [HttpPost]
        public PartialViewResult DetalleRemove(Guid guid)
        {
            //- Eliminamos el Item
            CacheManager.Get<List<EnvioDetalleBase>>("EnvioDetalleBase")
                .RemoveAll(x => x.Guid == guid);

            //- Actaulizamos los datos
            CacheManager.Get<EnvioViewModel>("EnvioViewModel").Entity.Detalle
                = CacheManager.Get<List<EnvioDetalleBase>>("EnvioDetalleBase");

            //- Devolvemos el model solo al detalle para refrezcar grilla
            return PartialView("_EnvioDetalle", CacheManager.Get<EnvioViewModel>("EnvioViewModel"));
        }

        [HttpPost]
        public PartialViewResult ItemAdd(Guid guid)
        {
            //- Incrementamos la cantidad
            foreach (var item in CacheManager.Get<List<EnvioDetalleBase>>("EnvioDetalleBase"))
                if (item.Guid == guid) item.Cantidad++;

            //- Actualizamos los datos
            CacheManager.Get<EnvioViewModel>("EnvioViewModel").Entity.Detalle
                = CacheManager.Get<List<EnvioDetalleBase>>("EnvioDetalleBase");

            //- Devolvemos el model solo al detalle para refrezcar grilla
            return PartialView("_EnvioDetalle", CacheManager.Get<EnvioViewModel>("EnvioViewModel"));
        }

        [HttpPost]
        public PartialViewResult ItemRemove(Guid guid)
        {
            //- Disminuimos la cantidad
            foreach (var item in CacheManager.Get<List<EnvioDetalleBase>>("EnvioDetalleBase"))
                if (item.Guid == guid && item.Cantidad > 1) item.Cantidad--;

            //- Actaulizamos los datos
            CacheManager.Get<EnvioViewModel>("EnvioViewModel").Entity.Detalle
                = CacheManager.Get<List<EnvioDetalleBase>>("EnvioDetalleBase");

            //- Devolvemos el model solo al detalle para refrezcar grilla
            return PartialView("_EnvioDetalle", CacheManager.Get<EnvioViewModel>("EnvioViewModel"));
        }

    }
}